// Program: drbest
// Original Author: Marta Murray-Close
// Date created: 05/30/19
// Last revised: 5/14/21 by Jacob Morris
// Changes made on 5/14/21:
// - Added lines 52-62 which fix the following issue:
// - - non-terminating decimals in drbest rounding.

/* This program rounds any of the following according to the DRB rounding rule
for estimates: (1) a number, (2) each element of a matrix, or (3) each variable 
of a variable list. */ 

/* The digits option allows the user to specify the number of significant 
digits the rounded output will have. The default is 4, the maximum allowed by 
the Disclosure Review Board. */

program define drbest_docinc, rclass
syntax anything [, digits(integer 4)]

/* Check argument type. */
capture confirm number `anything'
if _rc != 0 {
	capture confirm matrix `anything'
	if _rc != 0 {
		capture confirm numeric variable `anything'
		if _rc != 0 {
			disp as error "argument must be a number, matrix, or list of numeric variables"
			exit
		}
	}
}

/* User entered number. */
capture confirm number `anything' 
if _rc == 0 {
	local x = `anything'
	if `x' == 0 return scalar rounded = 0
	else return scalar rounded = round(`x',10^(floor(log10(abs(`x')))-(`digits'-1)))
}

/* User entered matrix. */
capture confirm matrix `anything'
if _rc == 0 {
	mat M = `anything'
	forval i = 1/`=rowsof(matrix(M))' {
	forval j = 1/`=colsof(matrix(M))' {
		local x = M[`i',`j']
		if `x' == 0 mat M[`i',`j'] = 0
		else mat M[`i',`j'] = round(`x',10^(floor(log10(abs(`x')))-(`digits'-1)))
	}
	}
	return matrix rounded = M
}

/* User entered variable. */
capture confirm numeric variable `anything' 
if _rc == 0 {
	foreach v of varlist `anything' {
		replace `v' = round(`v',10^(floor(log10(abs(`v')))-(`digits'-1))) if `v' != 0
		gen `v'_str = string(`v')
		destring(`v'_str), replace
		drop `v'
		rename `v'_str `v'
	}
}

end
